import {Application} from 'pinus';
import {FrontendSession} from 'pinus';
import {Code, OnlineStatus, UserStatus} from "../../../consts/code";
import { UserService } from '../../../services/userService';
import {Token} from "../../../util/token";
import {getLogger} from "pinus-logger";
const logger = getLogger("entryHandler")

export default function (app: Application) {
    return new EntryHandler(app);
}

export class EntryHandler {
    private _userService: UserService
    private _secret: {key: string, useful: number}
    constructor(private app: Application) {
        this._userService = this.app.get('userService')
        this._secret = this.app.get('secret')
    }
    /**
     * New client entry fish server.
     * @param  {Object}   msg     request message
     * @param  {Object}   session current session object
     */
    async entry(msg: { token:string }, session: FrontendSession) {
        if (!msg.token) {
            return { code: Code.ERROR_PARAM}
        }
        const authInfo = Token.parse(msg.token, this._secret.key)
        if (!authInfo) {
            return { code: Code.ERROR_TOKEN }
        }
        if (!Token.check(authInfo, this._secret.useful)) {
            return { code: Code.INVALID_TOKEN }
        }
        if(!!session.uid) {
            return {code: Code.ERROR_REPEAT}
        }
        const uid = authInfo.uid
        const sessionService = this.app.get('sessionService')
        // 是否玩家还在
        if(!!sessionService.getByUid(authInfo.uid)) {
            await sessionService.akick(uid, 'uid alread has session!!!')
        }
        // 玩家上线
        session.on('closed', this.onUserLeave.bind(this))
        await session.abind(uid)
        // 读取玩家数据
        try {
            await this._userService.updateUserOnline(parseInt(uid), OnlineStatus.ONLINE)
        } catch (err) {
            logger.warn("update user online fail")
        }

        return {code: Code.OK, data: {}}
    }
    /**
     * User log out handler
     *
     * @param {Object} app current application
     * @param {Object} session current session object
     *
     */
    private async onUserLeave(session: FrontendSession) {
        if (!session || !session.uid) {
            return;
        }
        let aviatorServers = this.app.getServersByType('aviator');
        if(!aviatorServers || aviatorServers.length === 0) {
            return;
        }
        // 玩家离线
        await this.app.rpc.aviator.remote.offline.toServer(aviatorServers[0].id ,parseInt(session.uid))
        try {
            await this._userService.updateUserOnline(parseInt(session.uid), OnlineStatus.OFFLINE)
        } catch(err) {
            logger.warn("update user offline fail")
        }
    }
}
